package main.leetcode.clockin.September;

import java.util.HashMap;
import java.util.Map;

/**
 * 剑指 Offer 20. 表示数值的字符串
 *
 * <p>请实现一个函数用来判断字符串是否表示数值（包括整数和小数）。
 *
 * <p>例如，字符串"+100"、"5e2"、"-123"、"3.1416"、"-1E-16"、"0123"都表示数值，但"12e"、"1a3.14"、"1.2.3"、"+-5"及"12e+5.4"都不是。
 */
public class day2 {
    private static Map[] status;

    static {
        status =
                new Map[] {
                    new HashMap<Type, Integer>(4) { // 0
                        {
                            put(Type.BLANK, 0);
                            put(Type.SIGN, 1);
                            put(Type.DOT, 2);
                            put(Type.DIGIT, 3);
                        }
                    },
                    new HashMap<Type, Integer>(3) { // 1
                        {
                            put(Type.DOT, 2);
                            put(Type.DIGIT, 3);
                        }
                    },
                    new HashMap<Type, Integer>(1) { // 2
                        {
                            put(Type.DIGIT, 5);
                        }
                    },
                    new HashMap<Type, Integer>(3) { // 3
                        {
                            put(Type.BLANK, 9);
                            put(Type.DOT, 4);
                            put(Type.DIGIT, 3);
                            put(Type.E, 6);
                        }
                    },
                    new HashMap<Type, Integer>(1) { // 4
                        {
                            put(Type.DIGIT, 5);
                            put(Type.BLANK, 9);
                            put(Type.E, 6);
                        }
                    },
                    new HashMap<Type, Integer>(3) { // 5
                        {
                            put(Type.BLANK, 9);
                            put(Type.DIGIT, 5);
                            put(Type.E, 6);
                        }
                    },
                    new HashMap<Type, Integer>(2) { // 6
                        {
                            put(Type.DIGIT, 8);
                            put(Type.SIGN, 7);
                        }
                    },
                    new HashMap<Type, Integer>(1) { // 7
                        {
                            put(Type.DIGIT, 8);
                        }
                    },
                    new HashMap<Type, Integer>(2) { // 8
                        {
                            put(Type.BLANK, 9);
                            put(Type.DIGIT, 8);
                        }
                    },
                    new HashMap<Type, Integer>(1) { // 9
                        {
                            put(Type.BLANK, 9);
                        }
                    },
                };
    }

    public static void main(String[] args) {
        //        System.out.println(new day2().isNumber(".+123"));
        //        System.out.println(new day2().isNumber("3."));
        //        System.out.println(new day2().isNumber("2e0"));
        String s =
                "\"{\\\"errorCode\\\":\\\"010003\\\",\\\"errorMsg\\\":\\\"参数校验失败: 身份证号码格式不正确\\\",\\\"result\\\":null,\\\"sign\\\":\\\"UbsHIDfcJxY4d2iFZrwye22MshMLkQ9wBqxkBdIRa1ygxtTDY1Pci2ox49A15AGv3Qhzt0AaOeacKASjwUrLWNz9eQioXUJu+wPIqU1IXbxKxAF2V2Ci3FmOmltlvDxwHW+WQ4aFxegE5ayFJ9P7IQooHDSYwY6pmCOIBqnw/vE=\\\",\\\"success\\\":false}\"";
        System.out.println(s.replaceAll("\\\\", ""));
    }

    public boolean isNumber(String s) {
        int index = 0;
        for (char c : s.toCharArray()) {
            Map<Type, Integer> next = status[index];
            Type cur = charToType(c);
            if (cur == null) {
                return false;
            }
            index = next.getOrDefault(cur, -1);
            if (index == -1) {
                return false;
            }
        }
        return index == 3 || index == 4 || index == 5 || index == 8 || index == 9;
    }

    private Type charToType(char c) {
        if (c == ' ') {
            return Type.BLANK;
        }
        if (c >= '0' && c <= '9') {
            return Type.DIGIT;
        }
        if (c == '.') {
            return Type.DOT;
        }
        if (c == '+' || c == '-') {
            return Type.SIGN;
        }
        if (c == 'e' || c == 'E') {
            return Type.E;
        }
        return null;
    }

    private enum Type {
        BLANK,
        SIGN,
        DIGIT,
        DOT,
        E
    }
}
